// 版权所有2011 Go作者。保留所有权利。
// 此源代码的使用受BSD样式
// 许可证的约束，该许可证可以在许可证文件中找到。

package bzip2

// moveToFrontDecoder实现移动到前一个列表。这样的列表是一种将包含重复元素的字符串转换为包含多个小数值的字符串的有效方法，适用于熵编码。它的工作原理是从一个符号的初始列表开始，并通过它们的索引将符号引用到该列表中。当一个符号被引用时，它会被移动到列表的前
// 处。因此，一个重复的符号最终被编码为许多零，因为在第一次访问后，该符号将位于列表的前面。
type moveToFrontDecoder []byte

// newMTFDecoder创建一个移动到前端的解码器，带有一个明确的符号初始列表
// 。
func newMTFDecoder(symbols []byte) moveToFrontDecoder {
	if len(symbols) > 256 {
		panic("too many symbols")
	}
	return moveToFrontDecoder(symbols)
}

// newMTFDecoderWithRange创建一个移动到前端的解码器，其初始值为
// 0的符号列表。。。n-1。
func newMTFDecoderWithRange(n int) moveToFrontDecoder {
	if n > 256 {
		panic("newMTFDecoderWithRange: cannot have > 256 symbols")
	}

	m := make([]byte, n)
	for i := 0; i < n; i++ {
		m[i] = byte(i)
	}
	return moveToFrontDecoder(m)
}

func (m moveToFrontDecoder) Decode(n int) (b byte) {
	// 只需一个简单的拷贝即可实现移动到前端。这种方法优于更复杂的基准测试方法，可能是
	// 因为它在
	// 单个缓存线内具有较高的引用局部性（大多数移动到前端操作的n<64）。
	b = m[n]
	copy(m[1:], m[:n])
	m[0] = b
	return
}

// 首先返回列表前面的符号。
func (m moveToFrontDecoder) First() byte {
	return m[0]
}
